/*
 * Buffer aware TTA decoder
 * christophe.paris <at> free.fr
 *
 * Based on ttacodec.c from foobar-tta-plugin
 *
 * Description:	 TTAv1 decoder for Sony PSP
 * Developed by: Alexander Djourik <sasha@iszf.irk.ru>
 *               Pavel Zhilin <pzh@iszf.irk.ru>
 *		 cooleyes <eyes.cooleyes@gmail.com>
 *
 * Copyright (c) 1999-2004 Alexander Djourik. All rights reserved.
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation; either version 2 of the License, or
 * (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * aint with this program; if not, write to the Free Software
 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
 *
 * Please see the file COPYING in this directory for full copyright
 * information.
 */

// ----------------------------------------------------------------------------

#ifdef _WIN32

#include <windows.h>
#include <mmreg.h>

#define tta_alloc(__length) GlobalAlloc(GMEM_ZEROINIT, __length)
#define tta_free(__dest) GlobalFree(__dest)
#define tta_memcpy(__buff1,__buff2,__length) CopyMemory(__buff1,__buff2,__length)
#define tta_memclear(__dest,__length) ZeroMemory(__dest,__length)
#define tta_memcmp(__buff1,__buff2,__length) memcmp(__buff1,__buff2,__length)

#else
#include <string.h>

#define WAVE_FORMAT_PCM	1
#define WAVE_FORMAT_IEEE_FLOAT 3

#define tta_alloc(__length) malloc(__length)
#define tta_free(__dest) free(__dest)
#define tta_memcpy(__buff1,__buff2,__length) memcpy(__buff1,__buff2,__length)
#define tta_memclear(__dest,__length) memset(__dest, 0, __length)
#define tta_memcmp(__buff1,__buff2,__length) memcmp(__buff1,__buff2,__length)

#endif

// ----------------------------------------------------------------------------
#include <stdlib.h>
#include <pspkernel.h>
#include "ttacodec.h"
#include "filters.h"
#include "crc32.h"

// ----------------------------------------------------------------------------

#define MAX(a,b)    (((a) > (b)) ? (a) : (b))
#define MIN(a,b)    (((a) < (b)) ? (a) : (b))

#ifdef _BIG_ENDIAN
#define	ENDSWAP_INT16(x)	(((((x)>>8)&0xFF)|(((x)&0xFF)<<8)))
#define	ENDSWAP_INT32(x)	(((((x)>>24)&0xFF)|(((x)>>8)&0xFF00)|(((x)&0xFF00)<<8)|(((x)&0xFF)<<24)))
#else
#define	ENDSWAP_INT16(x)	(x)
#define	ENDSWAP_INT32(x)	(x)
#endif

#define SWAP16(x) (\
	(((x)&(1<< 0))?(1<<15):0) | \
	(((x)&(1<< 1))?(1<<14):0) | \
	(((x)&(1<< 2))?(1<<13):0) | \
	(((x)&(1<< 3))?(1<<12):0) | \
	(((x)&(1<< 4))?(1<<11):0) | \
	(((x)&(1<< 5))?(1<<10):0) | \
	(((x)&(1<< 6))?(1<< 9):0) | \
	(((x)&(1<< 7))?(1<< 8):0) | \
	(((x)&(1<< 8))?(1<< 7):0) | \
	(((x)&(1<< 9))?(1<< 6):0) | \
	(((x)&(1<<10))?(1<< 5):0) | \
	(((x)&(1<<11))?(1<< 4):0) | \
	(((x)&(1<<12))?(1<< 3):0) | \
	(((x)&(1<<13))?(1<< 2):0) | \
	(((x)&(1<<14))?(1<< 1):0) | \
(((x)&(1<<15))?(1<< 0):0))

#define PREDICTOR1(x, k)	((long)((((uint64)x << k) - x) >> k))

#define ENC(x)  (((x)>0)?((x)<<1)-1:(-(x)<<1))
#define DEC(x)  (((x)&1)?(++(x)>>1):(-(x)>>1))

// ----------------------------------------------------------------------------

const unsigned long bit_mask[] = {
    0x00000000, 0x00000001, 0x00000003, 0x00000007,
		0x0000000f, 0x0000001f, 0x0000003f, 0x0000007f,
		0x000000ff, 0x000001ff, 0x000003ff, 0x000007ff,
		0x00000fff, 0x00001fff, 0x00003fff, 0x00007fff,
		0x0000ffff, 0x0001ffff, 0x0003ffff, 0x0007ffff,
		0x000fffff, 0x001fffff, 0x003fffff, 0x007fffff,
		0x00ffffff, 0x01ffffff, 0x03ffffff, 0x07ffffff,
		0x0fffffff, 0x1fffffff, 0x3fffffff, 0x7fffffff,
		0xffffffff
};

const unsigned long bit_shift[] = {
    0x00000001, 0x00000002, 0x00000004, 0x00000008,
		0x00000010, 0x00000020, 0x00000040, 0x00000080,
		0x00000100, 0x00000200, 0x00000400, 0x00000800,
		0x00001000, 0x00002000, 0x00004000, 0x00008000,
		0x00010000, 0x00020000, 0x00040000, 0x00080000,
		0x00100000, 0x00200000, 0x00400000, 0x00800000,
		0x01000000, 0x02000000, 0x04000000, 0x08000000,
		0x10000000, 0x20000000, 0x40000000, 0x80000000,
		0x80000000, 0x80000000, 0x80000000, 0x80000000,
		0x80000000, 0x80000000, 0x80000000, 0x80000000
};

const unsigned long *shift_16 = bit_shift + 4;

/************************* bit operations ******************************/

void bit_buffer_free(TTA_bit_buffer* bbuf) {
	if(bbuf)
	{
		if(bbuf->bit_buffer)
		{
			bbuf->bitpos = NULL;
			bbuf->BIT_BUFFER_END = NULL;
			tta_free(bbuf->bit_buffer);
			bbuf->bit_buffer = NULL;
		}
		tta_free(bbuf);
	}
}

TTA_bit_buffer* bit_buffer_new(unsigned long size) {
	TTA_bit_buffer* bbuf = tta_alloc(sizeof(TTA_bit_buffer));
	if(!bbuf)
		return NULL;
	bbuf->size = size + 8;
	bbuf->bit_buffer = tta_alloc(size + 8);
	if(!bbuf->bit_buffer)
	{
		bit_buffer_free(bbuf);
		return NULL;
	}
	bbuf->BIT_BUFFER_END = bbuf->bit_buffer + bbuf->size;
	return bbuf;
}

void bit_buffer_init_write(TTA_bit_buffer* bbuf) {
    bbuf->crc32 = 0xFFFFFFFFUL;
    bbuf->bit_count = bbuf->bit_cache = 0;
    bbuf->bitpos = bbuf->bit_buffer;	
}

void bit_buffer_init_read(TTA_bit_buffer* bbuf) {
    bbuf->crc32 = 0xFFFFFFFFUL;
    bbuf->bit_count = bbuf->bit_cache = 0;
    bbuf->bitpos = bbuf->BIT_BUFFER_END;
}

__inline void bit_buffer_put_binary(TTA_bit_buffer* bbuf, unsigned long value, unsigned long bits) {
    while (bbuf->bit_count >= 8) {
		*bbuf->bitpos = (unsigned char) (bbuf->bit_cache & 0xFF);
		UPDATE_CRC32(*bbuf->bitpos, bbuf->crc32);
		bbuf->bit_cache >>= 8;
		bbuf->bit_count -= 8;
		bbuf->bitpos++;
    }

    bbuf->bit_cache |= (value & bit_mask[bits]) << bbuf->bit_count;
    bbuf->bit_count += bits;
}

__inline void bit_buffer_get_binary(TTA_bit_buffer* bbuf, unsigned long *value, unsigned long bits) {
    while (bbuf->bit_count < bits) {		
		UPDATE_CRC32(*bbuf->bitpos, bbuf->crc32);
		bbuf->bit_cache |= *bbuf->bitpos << bbuf->bit_count;
		bbuf->bit_count += 8;
		bbuf->bitpos++;
    }
	
    *value = bbuf->bit_cache & bit_mask[bits];
    bbuf->bit_cache >>= bits;
    bbuf->bit_count -= bits;
    bbuf->bit_cache &= bit_mask[bbuf->bit_count];
}

__inline void bit_buffer_put_unary(TTA_bit_buffer* bbuf, unsigned long value) {
    do {
		while (bbuf->bit_count >= 8) {
			*bbuf->bitpos = (unsigned char) (bbuf->bit_cache & 0xFF);
			UPDATE_CRC32(*bbuf->bitpos, bbuf->crc32);
			bbuf->bit_cache >>= 8;
			bbuf->bit_count -= 8;
			bbuf->bitpos++;
		}

		if (value > 23) {
			bbuf->bit_cache |= bit_mask[23] << bbuf->bit_count;
			bbuf->bit_count += 23;
			value -= 23;
		} else {
			bbuf->bit_cache |= bit_mask[value] << bbuf->bit_count;
			bbuf->bit_count += value + 1;
			value = 0;
		}
    } while (value);
}

__inline void bit_buffer_get_unary(TTA_bit_buffer* bbuf, unsigned long *value) {
    *value = 0;
	
    while (!(bbuf->bit_cache ^ bit_mask[bbuf->bit_count])) {	
		*value += bbuf->bit_count;
		bbuf->bit_cache = *bbuf->bitpos++;
		UPDATE_CRC32(bbuf->bit_cache, bbuf->crc32);
		bbuf->bit_count = 8;
    }
	
    while (bbuf->bit_cache & 1) {
		(*value)++;
		bbuf->bit_cache >>= 1;
		bbuf->bit_count--;
    }
	
    bbuf->bit_cache >>= 1;
    bbuf->bit_count--;
}

int bit_buffer_done_write(TTA_bit_buffer* bbuf) {
    unsigned long bytes_to_write;

    while (bbuf->bit_count) {
		*bbuf->bitpos = (unsigned char) (bbuf->bit_cache & 0xFF);
		UPDATE_CRC32(*bbuf->bitpos, bbuf->crc32);
		bbuf->bit_cache >>= 8;
		bbuf->bit_count = (bbuf->bit_count > 8) ? (bbuf->bit_count - 8) : 0;
		bbuf->bitpos++;
    }

    bbuf->crc32 ^= 0xFFFFFFFFUL;
    bbuf->crc32 = ENDSWAP_INT32(bbuf->crc32);
    tta_memcpy(bbuf->bitpos, &bbuf->crc32, 4);
    bytes_to_write = bbuf->bitpos + sizeof(long) - bbuf->bit_buffer;

    bbuf->bitpos = bbuf->bit_buffer;
    bbuf->crc32 = 0xFFFFFFFFUL;

    return bytes_to_write;
}

int bit_buffer_done_read(TTA_bit_buffer* bbuf) {
    unsigned long crc32, res;
    bbuf->crc32 ^= 0xFFFFFFFFUL;
	
    memcpy(&crc32, bbuf->bitpos, 4);
    crc32 = ENDSWAP_INT32(crc32);
    bbuf->bitpos += sizeof(long);
    res = (crc32 != bbuf->crc32);
	
    bbuf->bit_cache = bbuf->bit_count = 0;
    bbuf->crc32 = 0xFFFFFFFFUL;
	
    return res;
}

/************************** WAV functions ******************************/

void convert_input_buffer(long *dst, unsigned char *src, long byte_size, unsigned long len)
{
	unsigned char *start = src;
	switch (byte_size) {
	case 1: for (; src < start + len; dst++)
				*dst = (signed long) *src++ - 0x80;
			break;
	case 2: for (; src < start + (len * 2); dst++) {
				*dst = (unsigned char) *src++;
				*dst |= (signed char) *src++ << 8;
			}
			break;
	case 3: for (; src < start + (len * 3); dst++) {
				*dst = (unsigned char) *src++;
				*dst |= (unsigned char) *src++ << 8;
				*dst |= (signed char) *src++ << 16;
			}
			break;
	case 4: for (; src < start + (len * 4); dst += 2) {
				*dst = (unsigned char) *src++;
				*dst |= (unsigned char) *src++ << 8;
				*dst |= (unsigned char) *src++ << 16;
				*dst |= (signed char) *src++ << 24;
			}
			break;
	}
}

long convert_output_buffer(unsigned char *dst, long *data, long byte_size,
						   long num_chan, unsigned long len)
{
	long *src = data;
	
	switch (byte_size) {
	case 1: for (; src < data + (len * num_chan); src++)
				*dst++ = (unsigned char) (*src + 0x80);
		break;
	case 2: for (; src < data + (len * num_chan); src++) {
		*dst++ = (unsigned char) *src;
		*dst++ = (unsigned char) (*src >> 8);
			}
		break;
	case 3: for (; src < data + (len * num_chan); src++) {
		*dst++ = (unsigned char) *src;
		*dst++ = (unsigned char) (*src >> 8);
		*dst++ = (unsigned char) (*src >> 16);
			}
		break;
	case 4: for (; src < data + (len * num_chan * 2); src += 2) {
		*dst++ = (unsigned char) *src;
		*dst++ = (unsigned char) (*src >> 8);
		*dst++ = (unsigned char) (*src >> 16);
		*dst++ = (unsigned char) (*src >> 24);
			}
		break;
    }
	
    return byte_size * len * num_chan;
}

/************************* basic functions *****************************/

void rice_init(TTA_adapt *rice, unsigned long k0, unsigned long k1) {
    rice->k0 = k0;
    rice->k1 = k1;
    rice->sum0 = shift_16[k0];
    rice->sum1 = shift_16[k1];
}

void channels_codec_init(TTA_channel_codec *ttacc, long nch, long byte_size) {
	long *fset = flt_set[byte_size - 1];
    long i;
	
    for (i = 0; i < nch; i++) {
		filter_init(&ttacc[i].fst, fset[0], fset[1]);
		rice_init(&ttacc[i].rice, 10, 10);
		ttacc[i].last = 0;
    }
}

#include <stdio.h>

unsigned long decompress_data(TTA_codec* ttacodec, long *data)
{
	long *p, value;
	unsigned long k, depth, unary, binary;
	unsigned long decoded_pcm_frames = 0;
	
	for (p = data; ; p++) {
		TTA_fltst *fst = &ttacodec->enc->fst;
		TTA_adapt *rice = &ttacodec->enc->rice;
		long *last = &ttacodec->enc->last;
		
		// decode Rice unsigned
		bit_buffer_get_unary(ttacodec->fbuf, &unary);
		
		switch (unary) {
		case 0: depth = 0; k = rice->k0; break;
		default:
			depth = 1; k = rice->k1;
			unary--;
		}
		
		if (k) {
			bit_buffer_get_binary(ttacodec->fbuf, &binary, k);
			value = (unary << k) + binary;
		} else value = unary;
		
		switch (depth) {
		case 1: 
			rice->sum1 += value - (rice->sum1 >> 4);
			if (rice->k1 > 0 && rice->sum1 < shift_16[rice->k1])
				rice->k1--;
			else if (rice->sum1 > shift_16[rice->k1 + 1])
				rice->k1++;
			value += bit_shift[rice->k0];
		default:
			rice->sum0 += value - (rice->sum0 >> 4);
			if (rice->k0 > 0 && rice->sum0 < shift_16[rice->k0])
				rice->k0--;
			else if (rice->sum0 > shift_16[rice->k0 + 1])
				rice->k0++;
		}
		
		*p = DEC(value);
		
		// decompress stage 1: adaptive hybrid filter
		hybrid_filter(fst, p, 0);
		
		// decompress stage 2: fixed order 1 prediction
		switch (ttacodec->byte_size) {
		case 1: *p += PREDICTOR1(*last, 4); break;	// bps 8
		case 2: *p += PREDICTOR1(*last, 5); break;	// bps 16
		case 3: *p += PREDICTOR1(*last, 5); break;	// bps 24
		case 4: *p += *last; break;		// bps 32
		} *last = *p;
		
		// combine data
		if (ttacodec->is_float && ((p - data) & 1)) {
			unsigned long negative = *p & 0x80000000;
			unsigned long data_hi = *(p - 1);
			unsigned long data_lo = abs(*p) - 1;
			
			data_hi += (data_hi || data_lo) ? 0x3F80 : 0;
			*(p - 1) = (data_hi << 16) | SWAP16(data_lo) | negative;
		}
		
		if (ttacodec->enc < ttacodec->tta + ttacodec->codec_num_chan - 1)
			ttacodec->enc++;
		else {
			if (!ttacodec->is_float && ttacodec->codec_num_chan > 1) {
				long *r = p - 1;
				*p += *(p - 1) / 2;
				while (r > p - ttacodec->codec_num_chan)
					*r = *(r + 1) - *r--;
			}
			ttacodec->enc = ttacodec->tta;
			decoded_pcm_frames++;
			if ( decoded_pcm_frames == ttacodec->blocks_per_loop ) //TTA_BLOCKS_PER_LOOP )
				break;
			// is it end of buffer ? mostly usefull for last frame
			if(ttacodec->fbuf->bitpos >= ttacodec->fbuf->BIT_BUFFER_END)
			{
				break;
			}
		}
	}
	return decoded_pcm_frames;
}

unsigned long decompress_frame(TTA_codec* ttacodec, long *data, unsigned long len)
{
	unsigned long decoded_pcm_frames = 0;
	
	if ( ttacodec->fbuf->bitpos >= ttacodec->fbuf->BIT_BUFFER_END ) {

		channels_codec_init(ttacodec->tta, ttacodec->codec_num_chan, ttacodec->byte_size);

		// Fill the bit buffer with the complete TTA frame
		tta_memcpy(ttacodec->fbuf->bit_buffer, data, len);
		ttacodec->fbuf->bitpos = ttacodec->fbuf->bit_buffer;
		ttacodec->fbuf->BIT_BUFFER_END = ttacodec->fbuf->bit_buffer + len - sizeof(ttacodec->fbuf->crc32);
	}
	decoded_pcm_frames = decompress_data(ttacodec, ttacodec->data);
	
	if ( ttacodec->fbuf->bitpos >= ttacodec->fbuf->BIT_BUFFER_END ) {
		// Check crc and reset bit buffer
		if (bit_buffer_done_read(ttacodec->fbuf)) {
			// wrong crc, "silence" frame
			//tta_memclear(ttacodec->data, len);
			bit_buffer_init_read(ttacodec->fbuf);
			//return 0;	// Skip this frame
		}
	}

	return decoded_pcm_frames;
}

TTA_codec* tta_codec_new(long srate, short num_chan, short bps, short format, long blocks_per_loop) {
	TTA_codec* ttacodec = tta_alloc(sizeof(TTA_codec));	
	if(!ttacodec)
		return NULL;
	
	ttacodec->framelen = (long)(TTA_FRAME_TIME * srate);
	ttacodec->srate = srate;
	ttacodec->num_chan = num_chan;
	ttacodec->bps = bps;
	ttacodec->blocks_per_loop = blocks_per_loop;
	ttacodec->byte_size = (bps + 7) / 8;
	ttacodec->is_float = (bps == 32) || (format == WAVE_FORMAT_IEEE_FLOAT);
	ttacodec->wavformat = format;
	ttacodec->codec_num_chan = (ttacodec->num_chan << ttacodec->is_float);
	
	ttacodec->fbuf = bit_buffer_new(ttacodec->framelen * ttacodec->byte_size *
		ttacodec->codec_num_chan * (ttacodec->is_float ? 2 : 1) + sizeof(long));
	if(!ttacodec->fbuf)
	{
		tta_codec_free(ttacodec);
		return NULL;
	}
	
	ttacodec->data_len = 0;
	ttacodec->data = (long *) tta_alloc(ttacodec->codec_num_chan *
		ttacodec->framelen * sizeof(long) * (ttacodec->is_float ? 2 : 1));
	if(!ttacodec->data)
	{
		tta_codec_free(ttacodec);
		return NULL;
	}
	
	ttacodec->enc = ttacodec->tta = tta_alloc(ttacodec->codec_num_chan *
		sizeof(TTA_channel_codec));
	if(!ttacodec->tta)
	{
		tta_codec_free(ttacodec);
		return NULL;
	}
	
	return ttacodec;
}

/************************* public functions *****************************/

// ----------------------------------------------------------------------------
// TTA codec common part
// ----------------------------------------------------------------------------

void tta_codec_free(TTA_codec* ttacodec) {
	if(ttacodec)
	{
		bit_buffer_free(ttacodec->fbuf);
		ttacodec->fbuf = NULL;
		if (ttacodec->data) {
			tta_free(ttacodec->data);
			ttacodec->data = NULL;
		}
		if (ttacodec->tta) {
			tta_free(ttacodec->tta = ttacodec->enc);
			ttacodec->enc = NULL;
			ttacodec->tta = NULL;
		}
		tta_free(ttacodec);
	}
}

void tta_codec_fill_header(TTA_codec* ttaenc, TTA_header *hdr, unsigned long data_len)
{
	hdr->TTAid = ENDSWAP_INT32(TTA1_SIGN);
	hdr->AudioFormat = ENDSWAP_INT16(ttaenc->wavformat);
	hdr->NumChannels = ENDSWAP_INT16(ttaenc->num_chan);
	hdr->BitsPerSample = ENDSWAP_INT16(ttaenc->bps);
	hdr->SampleRate = ENDSWAP_INT32(ttaenc->srate);
	hdr->DataLength = ENDSWAP_INT32(data_len);
	hdr->CRC32 = crc32((unsigned char *) &hdr, sizeof(TTA_header) - sizeof(long));
	hdr->CRC32 = ENDSWAP_INT32(hdr->CRC32);
}

unsigned long tta_codec_get_frame_len(long srate) {
	return (long)(TTA_FRAME_TIME * srate);
}

// ----------------------------------------------------------------------------
// TTA codec decoder part
// ----------------------------------------------------------------------------

TTA_codec* tta_codec_decoder_new(long srate, short num_chan, short bps, long blocks_per_loop)
{
	TTA_codec* ttadec = tta_codec_new(srate, num_chan, bps, 0, blocks_per_loop);
	if(ttadec) {
		// decoder specific init
		bit_buffer_init_read(ttadec->fbuf);
	}
	
	return ttadec;
}


unsigned long tta_codec_decoder_decode_frame(TTA_codec* ttadec, void *src,
	unsigned long len, void *dst) {
		
	unsigned long decoded_pcm_frames = 0;

	decoded_pcm_frames = decompress_frame(ttadec, (unsigned long*)src, len);

	convert_output_buffer(dst, ttadec->data, ttadec->byte_size,
		ttadec->num_chan, decoded_pcm_frames);
	
	return decoded_pcm_frames;
}

// ----------------------------------------------------------------------------
// TTA parser functions
// ----------------------------------------------------------------------------

TTA_parser* tta_parser_new(const char* filename)
{
	unsigned long i, checksum, st_size;

	TTA_parser* ttaparser = tta_alloc(sizeof(TTA_parser));
	if(!ttaparser)
		return NULL;
	ttaparser->ioHandle = -1;
	ttaparser->ioHandle = sceIoOpen(filename, PSP_O_RDONLY, 0777);
	if ( ttaparser->ioHandle < 0) {
		tta_free(ttaparser);
		return NULL;
	}
	ttaparser->DataOffset = 0;

	// Skip ID3V2 header if any ( http://www.id3.org/id3v2.4.0-structure.txt )
	if ( sceIoRead( ttaparser->ioHandle, &ttaparser->id3v2, sizeof(TTA_id3v2_header) ) !=  sizeof(TTA_id3v2_header))
	{
		tta_free(ttaparser);
		return NULL;
	}
	
	if (!tta_memcmp(ttaparser->id3v2.id, "ID3", 3)) {	
		if ((ttaparser->id3v2.size[0] |
			 ttaparser->id3v2.size[1] |
			 ttaparser->id3v2.size[2] |
			 ttaparser->id3v2.size[3]) & 0x80) {
			return NULL;
		}
		
		ttaparser->ID3v2Len = (ttaparser->id3v2.size[0] << 21) |
			(ttaparser->id3v2.size[1] << 14) |
			(ttaparser->id3v2.size[2] << 7) |
			ttaparser->id3v2.size[3];
		ttaparser->ID3v2Len += 10;
		if (ttaparser->id3v2.flags & (1 << 4))
			ttaparser->ID3v2Len += 10; // Footer present
		if ( sceIoLseek32(ttaparser->ioHandle, ttaparser->ID3v2Len, PSP_SEEK_CUR) < 0  ) {
			tta_free(ttaparser);
			return NULL;
		}
		ttaparser->DataOffset = sizeof(TTA_id3v2_header) + ttaparser->ID3v2Len;
	} else {
		if ( sceIoLseek32(ttaparser->ioHandle, 0, PSP_SEEK_SET)  < 0 ) {
			tta_free(ttaparser);
			return NULL;
		}		
	}

	// Read TTA header now
	if ( sceIoRead( ttaparser->ioHandle, &ttaparser->TTAHeader, sizeof(TTA_header) ) !=  sizeof(TTA_header)) 
	{
		tta_free(ttaparser);
		return NULL;
	}
	ttaparser->DataOffset += sizeof(TTA_header);

	// Check for supported formats
	if (ENDSWAP_INT32(ttaparser->TTAHeader.TTAid) != TTA1_SIGN) {
		tta_free(ttaparser);
		return NULL;
	}
	
	ttaparser->TTAHeader.CRC32 = ENDSWAP_INT32(ttaparser->TTAHeader.CRC32);
	// Check header crc32 
	checksum = crc32((unsigned char *) &ttaparser->TTAHeader,
		sizeof(TTA_header) - sizeof(long));
	if (checksum != ttaparser->TTAHeader.CRC32) {
		tta_free(ttaparser);
		return NULL;
	}
	
	ttaparser->TTAHeader.AudioFormat = ENDSWAP_INT16(ttaparser->TTAHeader.AudioFormat);
	ttaparser->TTAHeader.NumChannels = ENDSWAP_INT16(ttaparser->TTAHeader.NumChannels);
	ttaparser->TTAHeader.BitsPerSample = ENDSWAP_INT16(ttaparser->TTAHeader.BitsPerSample);
	ttaparser->TTAHeader.SampleRate = ENDSWAP_INT32(ttaparser->TTAHeader.SampleRate);
	ttaparser->TTAHeader.DataLength = ENDSWAP_INT32(ttaparser->TTAHeader.DataLength);
	
	ttaparser->FrameLen = tta_codec_get_frame_len(ttaparser->TTAHeader.SampleRate);
	ttaparser->LastFrameLen = ttaparser->TTAHeader.DataLength % ttaparser->FrameLen;
	ttaparser->FrameTotal = ttaparser->TTAHeader.DataLength / ttaparser->FrameLen +
		(ttaparser->LastFrameLen ? 1 : 0);
	st_size = (ttaparser->FrameTotal + 1); // +1 for crc32

	// This table contain the length in bytes of each frame
	ttaparser->SeekTable = tta_alloc(st_size * sizeof(long));

	// This table contain the start offset in bytes of each frame
	ttaparser->SeekOffsetTable = tta_alloc(st_size * sizeof(long));
	
	// Read seek table
	if ( sceIoRead( ttaparser->ioHandle, ttaparser->SeekTable, st_size * sizeof(long) ) !=  st_size * sizeof(long))	
	{
		tta_free(ttaparser);
		return NULL;
	}
	ttaparser->DataOffset += (st_size * sizeof(long));
	
	// Check seek table crc32
	checksum = crc32((unsigned char *) ttaparser->SeekTable, ((st_size - 1) * sizeof(long)));
	if (checksum != ttaparser->SeekTable[st_size - 1])
	{
		// Seek table corrupted
		tta_free(ttaparser);
		return NULL;
	}

	// Compute SeekOffsetTable
	ttaparser->SeekOffsetTable[0] = ttaparser->DataOffset;
	for(i = 1; i < (st_size-1); i++)
	{		
		ttaparser->SeekOffsetTable[i] = ttaparser->SeekOffsetTable[i-1] + ttaparser->SeekTable[i-1];
	}

	// Compute MaxFrameLenBytes
	ttaparser->MaxFrameLenBytes = 0;
	for(i = 0; i < (st_size-1); i++)
	{		
		if(ttaparser->SeekTable[i] > ttaparser->MaxFrameLenBytes)
			ttaparser->MaxFrameLenBytes = ttaparser->SeekTable[i];
	}

	// Ready to start
	ttaparser->FrameIndex = 0;
		
	return ttaparser;
}

unsigned char* tta_parser_read_frame(TTA_parser* ttaparser,
									unsigned long* FrameIndex,
									unsigned long* FrameLen,
									unsigned long* FrameLenBytes)
{
	unsigned long CurrentFrameLen;

	if(tta_parser_eof(ttaparser))
		return NULL;

	CurrentFrameLen = ttaparser->FrameLen;
	if(ttaparser->FrameIndex == (ttaparser->FrameTotal - 1))
		CurrentFrameLen = ttaparser->LastFrameLen;
	*FrameLenBytes = ttaparser->SeekTable[ttaparser->FrameIndex];
	
	unsigned char* dst = (unsigned char*)malloc(*FrameLenBytes);
	if (dst == NULL)
		return NULL;
	
	if ( sceIoRead( ttaparser->ioHandle, dst, *FrameLenBytes) != *FrameLenBytes)
	{
		free(dst);
		return NULL;
	}
	
	*FrameIndex = ttaparser->FrameIndex;
	*FrameLen = CurrentFrameLen;

	ttaparser->FrameIndex++;

	return dst;
}

void tta_parser_seek(TTA_parser* ttaparser, uint64 seek_pos_100ns)
{
	// Find at which frame we need to seek	
	ttaparser->FrameIndex = (long)(seek_pos_100ns / (TTA_FRAME_TIME * 10000000));
	if(tta_parser_eof(ttaparser))
		return;
	sceIoLseek32( ttaparser->ioHandle, ttaparser->SeekOffsetTable[ttaparser->FrameIndex], PSP_SEEK_SET);
}

int tta_parser_eof(TTA_parser* ttaparser)
{
	return (ttaparser->FrameIndex >= ttaparser->FrameTotal);
}

void tta_parser_free(TTA_parser** ttaparser)
{
	if(!(*ttaparser))
		return;
		
	if ( (*ttaparser)->ioHandle >= 0)
	{
		sceIoClose((*ttaparser)->ioHandle);
		(*ttaparser)->ioHandle = -1;
	}

	if((*ttaparser)->SeekOffsetTable)
	{
		tta_free((*ttaparser)->SeekOffsetTable);
		(*ttaparser)->SeekOffsetTable = NULL;
	}

	if((*ttaparser)->SeekTable)
	{
		tta_free((*ttaparser)->SeekTable);
		(*ttaparser)->SeekTable = NULL;
	}

	tta_free(*ttaparser);
	*ttaparser = NULL;
}

unsigned long tta_crc32 (unsigned char *buffer, unsigned long len) {
	return crc32(buffer, len);
}
